/**
 * rest obj null, waring: no recursion
 * @param {obj} obj object
 */
export function resetObj (obj) {
  if (obj) {
    switch (typeof obj) {
      case 'number':
        obj = ''
        break
      case 'boolean':
        obj = ''
        break
      case 'string':
        obj = ''
        break
      case 'object':
        if (Array.isArray(obj)) {
          obj = []
        } else {
          if (isJSON(obj)) {
            for (let key in obj) {
              Array.isArray(obj[key]) ? obj[key] = [] : obj[key] = ''
            }
          } else {
            obj = null
          }
        }
        break
      default:
        obj = null
    }
  }
  return obj
}

export function isJSON (obj) {
  let temp = typeof obj !== 'string' ? JSON.stringify(obj) : obj
  try {
    temp = JSON.parse(temp)
  } catch (e) {
    return false
  }
  if (typeof temp === 'object' && temp !== null) {
    return true
  }
  return false
}

/**
 * set node undefined, if node vaule is []
 * @param {*} tree tree data array
 * @param {*} node check node key name
 */
export function refactTreeData (tree, node) {
  if (tree && tree.length > 0) {
    for (const branch of tree) {
      if (branch) {
        for (const key in branch) {
          if (key === node) {
            if (branch[key] && branch[key].length < 1) {
              // console.debug(`refactTreeData find ${key} is null`)
              branch[key] = undefined
            } else {
              refactTreeData(branch[key], key)
            }
            break
          }
        }
      }
    }
  }
  return tree
}

export function findTreeNode (tree, nodeKey, nodeValue) {
  if (tree && tree.length > 0) {
    for (const branch of tree) {
      if (branch) {
        for (const key in branch) {
          if (key === nodeKey) {
            if (branch[key] === nodeValue) {
              return branch
            }
            break
          } else if (branch[key] && Array.isArray(branch[key])) {
            let result = findTreeNode(branch[key], nodeKey, nodeValue)
            if (result) { return result }
          }
        }
      }
    }
  }
  return null
}

export function findTreeNodeForFSG (tree, nodeKey, nodeValue) {
  if (tree) {
    if (Array.isArray(tree)) {
      for (const branch of tree) {
        if (branch) {
          for (const key in branch) {
            if (key === nodeKey) {
              if (branch[key] === nodeValue) {
                return branch
              }
              break
            } else if (branch[key] && Array.isArray(branch[key])) {
              let result = findTreeNodeForFSG(branch[key], nodeKey, nodeValue)
              if (result) { return result }
            } else if (branch[key] && isJSON(branch[key])) {
              let result = findTreeNodeForFSG(branch[key], nodeKey, nodeValue)
              if (result) { return result }
            }
          }
        }
      }
    } else if (tree && isJSON(tree)) {
      let branch = tree
      for (const key in branch) {
        if (key === nodeKey) {
          if (branch[key] === nodeValue) {
            return branch
          }
          break
        } else if (branch[key] && Array.isArray(branch[key])) {
          let result = findTreeNodeForFSG(branch[key], nodeKey, nodeValue)
          if (result) { return result }
        } else if (branch[key] && isJSON(branch[key])) {
          let result = findTreeNodeForFSG(branch[key], nodeKey, nodeValue)
          if (result) { return result }
        }
      }
    }
  }
  return null
}

export function findTreeNodeQuickly (tree, nodeKey, nodeValue, childrenKey = 'children') {
  if (tree && tree.length > 0) {
    for (const branch of tree) {
      if (branch) {
        if (branch[nodeKey] === nodeValue) {
          return branch
        } else {
          if (branch[childrenKey]) {
            let result = findTreeNode(branch[childrenKey], nodeKey, nodeValue, childrenKey)
            if (result) { return result }
          }
        }
      }
    }
  }
  return null
}

export function findTreeNodeCb (tree, nodeKey, cb) {
  if (tree && tree.length > 0) {
    for (const branch of tree) {
      if (branch) {
        for (const key in branch) {
          if (key === nodeKey) {
            if (cb(branch[key])) {
              return branch
            }
          } else if (branch[key] && Array.isArray(branch[key])) {
            let result = findTreeNodeCb(branch[key], nodeKey, cb)
            if (result) { return result }
          }
        }
      }
    }
  }
  return null
}

export function findTreeNodeCbQuickly (tree, nodeKey, cb, childrenKey = 'children') {
  if (tree && tree.length > 0) {
    for (const branch of tree) {
      if (branch) {
        if (cb(branch[nodeKey])) {
          return branch
        } else {
          if (branch[childrenKey]) {
            let result = findTreeNodeCbQuickly(branch[childrenKey], nodeKey, cb, childrenKey)
            if (result) { return result }
          }
        }
      }
    }
  }
  return null
}

export function refactTreeCptData (tree, node, labelKey = 'name', valueKey = 'id', label = 'label', value = 'value') {
  if (tree && tree.length > 0) {
    for (const branch of tree) {
      if (branch) {
        for (const key in branch) {
          if (key === node) {
            if (branch[key] && branch[key].length < 1) {
              branch[key] = []
            } else {
              refactTreeCptData(branch[key], node, labelKey, valueKey, label, value)
            }
            break
          }
        }
        branch[label] = branch[labelKey]
        branch[value] = branch[valueKey]
      }
    }
  }
  return tree
}

export function refactTreeCptDataCb (tree, node, cb) {
  if (tree && tree.length > 0) {
    for (const branch of tree) {
      if (branch) {
        for (const key in branch) {
          if (key === node) {
            if (branch[key] && branch[key].length < 1) {
              branch[key] = []
            } else {
              refactTreeCptDataCb(branch[key], node, cb)
            }
            break
          }
        }
        if (cb instanceof Function) {
          cb(branch)
        }
      }
    }
  }
  return tree
}

export function isNumber (n) {
  return !isNaN(parseFloat(n)) && isFinite(n)
}

export function isFullJsonObj (jsonObj) {
  let orgValues = Object.values(jsonObj)
  let validValues = orgValues.filter((e) => { return e })
  return orgValues.length === validValues.length
}

export function filterJsonKey (jsonObj, ...keyFilters) {
  let obj = {}
  if (keyFilters && keyFilters.length > 0) {
    for (const key in jsonObj) {
      let find = keyFilters.some(function (k) { return key === k })
      if (!find) { obj[key] = jsonObj[key] }
    }
  } else {
    obj = jsonObj
  }
  return obj
}

export function filterJsonNullValue (jsonObj) {
  let obj = {}
  if (isJSON(jsonObj)) {
    for (const key in jsonObj) {
      let value = jsonObj[key]
      if (value || value === 0) {
        if (Array.isArray(value)) {
          if (value.length < 1) { continue }
        }
        obj[key] = value
      }
    }
  }
  return obj
}

export function isNullJsonKey (jsonObj, ...keys) {
  if (keys && keys.length > 0) {
    for (const key in jsonObj) {
      let find = keys.some(function (k) { return key === k })
      if (find && !jsonObj[key]) { return true }
    }
  }
  return false
}

export function isFullNumberValueJsonObj (jsonObj) {
  let orgValues = Object.values(jsonObj)
  let validValues = orgValues.filter((e) => {
    return isNumber(e)
  })
  return orgValues.length === validValues.length
}

export function isFullNumberValue (jsonObj, key) {
  let orgValues = Object.values(jsonObj)
  let validValues = orgValues.filter((e) => {
    if (e) {
      if (Array.isArray(e)) {
        for (const item of e) {
          if (key) {
            if (!isNumber(item[key])) { return false }
          } else {
            if (!isNumber(item)) { return false }
          }
        }
        return true
      }
      return isNumber(e)
    }
    return false
  })
  return orgValues.length === validValues.length
}

export function copyJsonObj (target, source) {
  if (isJSON(source)) {
    if (!target || !isJSON(target) || Object.keys(target).length < 1) {
      target = source
    } else {
      let sourceKeys = Object.keys(source)
      for (const key in target) {
        let find = sourceKeys.some(function (k) { return key === k })
        if (find && source[key] !== null) { target[key] = source[key] }
      }
    }
  } else {
    target = source
  }
  return target
}

export function getValueByKeys (jsonObj, keys) {
  if (Array.isArray(keys)) {
    let length = keys.length
    if (length > 1) {
      let temp
      for (let index = 0; index < length; index++) {
        const element = keys[index]
        if (index === 0) {
          temp = jsonObj[element]
        } else if (index === (length - 1)) {
          return temp[element]
        } else {
          temp = temp[element]
        }
      }
    } else if (length === 1) {
      return jsonObj[keys[0]]
    } else {
      return undefined
    }
  } else {
    return jsonObj[keys]
  }
}

/**
 * json对象转字符串，包含对象中数组字段的处理
 * @param {object} jsonObj json对象
 */
export function stringifyJsonObj (jsonObj) {
  let obj = JSON.parse(JSON.stringify(jsonObj))
  Object.keys(obj).forEach(item => {
    if (Array.isArray(obj[item])) {
      obj[item] = JSON.stringify(obj[item])
    }
  })
  return obj
}

/**
 * 检查数组元素是否有重复
 * 有重复返回true
 * @param arr 数组
 */
export function checkArrayItemsIsDuplicate (arr) {
  if (!arr) {
    return false
  }
  let [ map, i, size ] = [ {}, 0, 0 ]
  for (i = 0, size = arr.length; i < size; i++) {
    console.log(arr[i])
    if (map[arr[i]]) {
      return true
    }
    map[arr[i]] = true
  }
  return false
}
